/*
*************************************************************************************************
*文件：bsp_lcd.c
*作者：fanwenl_
*版本：V0.0.1
*日期：2016-06-01
*描述：STM32F469NI-Discovery开发套件4"TFT液晶驱动程序。
**************************************************************************************************
*/

#include "bsp_lcd.h"

uint8_t LCD_Init(LCD_OrientationTypeDef orientation)
{
	static LTDC_HandleTypeDef LTDC_Handle;
	static DSI_HandleTypeDef	DSI_Handle;
	static DSI_PLLInitTypeDef	DSI_PLLInit;
	static DSI_VidCfgTypeDef  DSI_VideoStru;
	static RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
	static uint32_t lcd_x_size;
	static uint32_t lcd_y_size;
	static uint32_t lcdClk = 27429;
	static uint32_t LaneByteClk_kHz = 62500;

	uint32_t VSA  				/*垂直同步段*/
	uint32_t VFP 				/*垂直前沿*/
	uint32_t VBP				/*垂直后沿*/
	uint32_t VACT				/*垂直有效像素*/
	
	uint32_t HSA				/*水平同步段*/
	uint32_t HFP				/*水平前沿*/
	uint32_t HBP				/*水平后沿*/
	uint32_t HACT				/*水平有效像素*/

	VSA = OTM8009A_480X800_VSYNC;  		/*1*/
	VFP =	OTM8009A_480X800_VFP;			/*16*/
	VBP = OTM8009A_480X800_VBP;			/*16*/
	
	HSA = OTM8009A_480X800_HSYN;			/*2*/
	HFP = OTM8009A_480X800_HFP;			/*20*/
	HBP = OTM8009A_480X800_HBP;			/*20*/

	if(orientation = LCD_ORIENTATION_PORTRAIT)/*竖屏显示模式*/
	{
		lcd_y_size = OTM8009A_480X800_HEIGHT;
		lcd_x_size = OTM8009A_480X800_WIDTH;
	}
	else
	{
		lcd_x_size = OTM8009A_800X480_WIDTH;
		lcd_y_size = OTM8009A_800X480_HEIGHT;
	}

	VACT = lcd_y_size;
	HACT = lcd_x_size;
/********************************DSI配置*********************************************/
	DSI_Handle.Instance = DSI;

	HAL_DSI_DeInit(&DSI_Handle);

	DSI_Handle.Init.AutomaticClockLaneControl = DSI_AUTO_CLK_LANE_CTRL_DISABLE; 
	/*TxEscapeCkdiv = (laneByClk_kHz (500MHz/8) /TxEsc),TxEsc最大20M这里4分频*/
	DSI_Handle.Init.TXEscapeCkdiv = 4;
	DSI_Handle.Init.NumberOfLanes = DSI_TWO_DATA_LANES;

	DSI_PLLInit.PLLNDIV = 125;
	DSI_PLLInit.PLLIDF  = DSI_PLL_IN_DIV2;
	DSI_PLLInit.PLLODF  = DSI_PLL_OUT_DIV1;

	HAL_DSI_Init(&DSI_Handle, &DSI_PLLInit);
	
	DSI_VideoStru.VirtualChannelID = LCD_OTM8009A_ID; /*定义LTDC和DSI接口的通道*/
	DSI_VideoStru.ColorCoding      = DSI_RGB888；/*定义DSI接口颜色模式*/
	DSI_VideoStru.LooselyPacked    = DSI_LOOSELY_PACKED_DISABLE； /*禁止Loosely*/
	DSI_VideoStru.Mode             = DSI_VID_MODE_BURST;/*视屏突发模式*/
	DSI_VideoStru.PacketSize       = HACT; /*水平像素有效值*/
	DSI_VideoStru.NumberOfChunks   = 0;
	DSI_VideoStru.NullPacketSize   = 0XFFF;
	DSI_VideoStru.HSPolarity       = DSI_HSYNC_ACTIVE_HIGH; /*HSYNC有效像素极性，和实际LCD芯片有关*/
	DSI_VideoStru.VSPolarity       = DSI_VSYNC_ACTIVE_HIGH;
	DSI_VideoStru.DEPolarity       = DSI_DATA_ENABLE_ACTIVE_HIGH;
	DSI_VideoStru.HorizontalSyncActive = 
	DSI_VideoStru.HorizontalBackPorch
	DSI_VideoStru.HorizontalLine
	DSI_VideoStru.VerticalSyncActive = VSA;
	DSI_VideoStru.VerticalBackPorch  = VBP; 
	DSI_VideoStru.VerticalFrontPorch = VFP;
	DSI_VideoStru.VerticalActive     = VACT;    
	DSI_VideoStru.LPCommandEnable = DSI_LP_COMMAND_ENABLE;   /*使能低功耗发送命令*/
	DSI_VideoStru.LPLargestPacketSize;
	DSI_VideoStru.LPVACTLargestPacketSize = ;
	DSI_VideoStru.LPHorizontalFrontPorchEnable = DSI_LP_HFP_ENABLE;
	DSI_VideoStru.LPHorizontalBackPorchEnable  = DSI_LP_HBP_ENABLE;
	DSI_VideoStru.LPVerticalActiveEnable       = DSI_LP_VACT_ENABLE;
	DSI_VideoStru.LPVerticalFrontPorchEnable   = DSI_LP_VFP_ENABLE;
	DSI_VideoStru.LPVerticalBackPorchEnable    = DSI_LP_VBP_ENABLE;
	DSI_VideoStru.LPVerticalSyncActiveEnable   = DSI_LP_VSYNC_ENABLE;
	DSI_VideoStru.FrameBTAAcknowledgeEnable; 

	 HAL_DSI_ConfigVideoMode(&DSI_Handle, &DSI_VideoStru);

	 HAL_DSI_Start(&DSI_Handle);

                                         
  uint32_t HorizontalSyncActive;         /*!< Horizontal synchronism active duration (in lane byte clock cycles) */
  uint32_t HorizontalBackPorch;          /*!< Horizontal back-porch duration (in lane byte clock cycles)         */
  uint32_t HorizontalLine;               /*!< Horizontal line duration (in lane byte clock cycles)               */
  uint32_t VerticalSyncActive;           /*!< Vertical synchronism active duration                               */
  uint32_t LPLargestPacketSize;          /*!< The size, in bytes, of the low power largest packet that
                                              can fit in a line during VSA, VBP and VFP regions                  */
  uint32_t LPVACTLargestPacketSize;      /*!< The size, in bytes, of the low power largest packet that
                                              can fit in a line during VACT region                               */
  uint32_t FrameBTAAcknowledgeEnable;    /*!< Frame bus-turn-around acknowledge enable
                                              This parameter can be any value of @ref DSI_FBTA_acknowledge       */
  HAL_DSI_ConfigVideoMode(&(hdsi_eval), &(hdsivideo_handle));
  
  /* Enable the DSI host and wrapper : but LTDC is not started yet at this stage */
  HAL_DSI_Start(&(hdsi_eval));
/*******************************LTDC配置*********************************************/
	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
	PeriphClkInitStruct.PLLSAI.PLLSAIN       = 384;
	PeriphClkInitStruct.PLLSAI.PLLSAIR       = 7;
	PeriphClkInitStruct.PLLSAIDivR           = RCC_PLLSAIDIVR_2;
	
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
	/*配置LTDC时序*/
	LTDC_Handle.Instance                = LTDC;    /*设置LTDC的寄存器地址*/
	
	LTDC_Handle.Init.PCPolarity         = LTDC_PCPOLARITY_IPC;
	
	LTDC_Handle.Init.HorizontalSync     = (HSA - 1);
	LTDC_Handle.Init.AccumulatedHBP     = (HSA + HBP - 1);
	
	LTDC_Handle.Init.AccumulatedActiveW = (lcd_x_size + HSA +HBP - 1);
	LTDC_Handle.Init.TotalWidth         = (lcd_x_size + HSA +HBP + HFP - 1);

	/*配置默认背景颜色*/
	LTDC_Handle.Init.Backcolor.blue  = 0 ;
	LTDC_Handle.Init.Backcolor.red   = 0 ;
	LTDC_Handle.Init.Backcolor.green = 0 ;

	HAL_LTDC_StructInitFromVideoConfig(LTDC_HandleTypeDef* hltdc, DSI_VidCfgTypeDef *VidCfg);

	HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc);

	/*复位LCD*/
	LCD_Reset();
	/*初始化DSI相关外设*/
	LCD_MspInit();
/********************************OTM8009A配置*********************************************/
	  
//	HAL_DSI_Init(,);
  
}
/*
**************************************************************************************************
*描述：LCD复位函数
*参数：无
*返回：无
*note：该函数是硬件复位，复位引脚链接在PH7
* ************************************************************************************************
 */
void LCD_Reset(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/*使能GPIOH的时钟*/
	__HAL_RCC_GPIOH_CLK_ENABLE();
	/*/*配置PH7的引脚为开漏输出*/
	GPIO_InitStructure.Pin   = GPIO_PIN_7;
	GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_OD;
	GPIO_InitStructure.Pull  = GPIO_NOPULL;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
	
	<HAL_GPI></HAL_GPI>O_Init(GPIOH,&GPIO_InitStructure);
	/*复位(低有效)*/
	HAL_GPIO_WritePin(GPIOH,GPIO_PIN_7,GPIO_PIN_RESET);

	HAL_Delay(20);延时20ms
	/*恢复*/
	HAL_GPIO_WritePin(GPIOH,GPIO_PIN_7,GPIO_PIN_SET);
	
	HAL_Delay(20);	
}
/*
**************************************************************************************************
*描述：DSI相关外设初始函数
*参数：无
*返回：无
*note：使能LTDC、DMA2D、DSI时钟，复位相关外设，配置DSI中断
* ************************************************************************************************
 */
void LCD_MspInit(void)
{
	/*使能LTDC时钟*/
   __HAL_RCC_LTDC_CLK_ENABLE();
	/*复位LTDC IP*/
	__HAL_RCC_LTDC_FORCE_RESET();
  	__HAL_RCC_LTDC_RELEASE_RESET();

	/*使能DMA2D时钟*/
   __HAL_RCC_DMA2D_CLK_ENABLE();
	/*复位DMA2D IP*/
	__HAL_RCC_DMA2D_FORCE_RESET();
  	__HAL_RCC_DMA2D_RELEASE_RESET();

	/*使能DSI时钟*/
   __HAL_RCC_DSI_CLK_ENABLE();
	/*复位DSI IP*/
	__HAL_RCC_DSI_FORCE_RESET();
  	__HAL_RCC_DSI_RELEASE_RESET();
	
	/*配置LTDC中断并使能该中断*/
/*	HAL_NVIC_SetPriority(LTDC_IRQn,3,0);
	HAL_NVIC_EnableIRQ(LTDC_IRQn);
*/
	/*配置DSI中断并使能该中断*/
	HAL_NVIC_SetPriority(DSI_IRQn,3,0);	/*这部分中断在哪里在哪里调用*/
	HAL_NVIC_EnableIRQ(DSI_IRQn);
}

